﻿using System;
using Notoric.Commanding.CommandBase;

namespace Notoric.ViewModel.Elements
{
    /// <summary>
    /// Adapts a <see cref="Model.Elements.PersonElement"/> to a Windows Presentation Foundation view.
    /// </summary>
    public class Person : ViewModelElement
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Person"/> class.
        /// </summary>
        /// <param name="adaptedElement">
        /// <para>
        /// Type: <see cref="Model.Elements.PersonElement"/>
        /// </para>
        /// <para>
        /// The adapted element.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="ViewModelElement"/>
        /// </para>
        /// <para>
        /// The owner.
        /// </para>
        /// </param>
        /// <param name="undoStack">
        /// <para>
        /// Type: <see cref="CommandStack"/>
        /// </para>
        /// <para>
        /// The undo stack.
        /// </para>
        /// </param>
        /// <param name="redoStack">
        /// <para>
        /// Type: <see cref="CommandStack"/>
        /// </para>
        /// <para>
        /// The redo stack.
        /// </para>
        /// </param>
        public Person(Model.Elements.PersonElement adaptedElement, ViewModelElement owner, CommandStack undoStack, CommandStack redoStack)
            : base(adaptedElement, owner, undoStack, redoStack)
        {
        }

        #endregion

        #region ViewModelElement Members

        /// <inheritdoc/>
        public override string ElementNameKey
        {
            get { return "ViewModel.ElementNames.Person"; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Creates an undoable command for setting the birth date.
        /// </summary>
        /// <param name="birthdate">
        /// <para>
        /// Type: <see cref="String"/>
        /// </para>
        /// <para>
        /// The birth date.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// The created command ready for use.
        /// </para>
        /// </returns>
        public UndoableCommandBase CreateSetBirthDateCommand(string birthdate)
        {
            return new SetterCommand<string>(this, "BirthDate", birthdate, UndoStack, RedoStack)
            {
                Name = "Change Birth Date"
            };
        }

        /// <summary>
        /// Creates an undoable command for setting the death date.
        /// </summary>
        /// <param name="deathdate">
        /// <para>
        /// Type: <see cref="String"/>
        /// </para>
        /// <para>
        /// The death date.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// The created command ready for use.
        /// </para>
        /// </returns>
        public UndoableCommandBase CreateSetDeathDateCommand(string deathdate)
        {
            return new SetterCommand<string>(this, "DeathDate", deathdate, UndoStack, RedoStack)
            {
                Name = "Change Death Date"
            };
        }

        /// <summary>
        /// Creates an undoable command for setting the first name.
        /// </summary>
        /// <param name="firstName">
        /// <para>
        /// Type: <see cref="String"/>
        /// </para>
        /// <para>
        /// The name.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// The created command ready for use.
        /// </para>
        /// </returns>
        public UndoableCommandBase CreateSetFirstNameCommand(string firstName)
        {
            return new SetterCommand<string>(this, "FirstName", firstName, UndoStack, RedoStack)
            {
                Name = "Change First Name"
            };
        }

        /// <summary>
        /// Creates an undoable command for setting the last name.
        /// </summary>
        /// <param name="lastName">
        /// <para>
        /// Type: <see cref="String"/>
        /// </para>
        /// <para>
        /// The name.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// The created command ready for use.
        /// </para>
        /// </returns>
        public UndoableCommandBase CreateSetLastNameCommand(string lastName)
        {
            return new SetterCommand<string>(this, "LastName", lastName, UndoStack, RedoStack)
            {
                Name = "Change Last Name"
            };
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the birth date.
        /// </summary>
        /// <value>The birth date.</value>
        public string BirthDate
        {
            get { return GetPropertyValue<string>("BirthDate"); }
            set
            {
                if (UnsavedChanges.ContainsKey("BirthDate"))
                {
                    var cmd = (SetterCommand<string>)UnsavedChanges["BirthDate"];
                    cmd.Value = value;
                }
                else
                    UnsavedChanges["BirthDate"] = CreateSetBirthDateCommand(value);

                RaisePropertyChanged("BirthDate");
            }
        }

        /// <summary>
        /// Gets or sets the death date.
        /// </summary>
        /// <value>The death date.</value>
        public string DeathDate
        {
            get { return GetPropertyValue<string>("DeathDate"); }
            set
            {
                if (UnsavedChanges.ContainsKey("DeathDate"))
                {
                    var cmd = (SetterCommand<string>)UnsavedChanges["DeathDate"];
                    cmd.Value = value;
                }
                else
                    UnsavedChanges["DeathDate"] = CreateSetDeathDateCommand(value);

                RaisePropertyChanged("DeathDate");
            }
        }

        /// <summary>
        /// Gets or sets the first name.
        /// </summary>
        /// <value>The first name.</value>
        public string FirstName
        {
            get { return GetPropertyValue<string>("FirstName"); }
            set
            {
                if (UnsavedChanges.ContainsKey("FirstName"))
                {
                    var cmd = (SetterCommand<string>)UnsavedChanges["FirstName"];
                    cmd.Value = value;
                }
                else
                    UnsavedChanges["FirstName"] = CreateSetFirstNameCommand(value);

                RaisePropertyChanged("FirstName");
            }
        }

        /// <summary>
        /// Gets or sets the last name.
        /// </summary>
        /// <value>The last name.</value>
        public string LastName
        {
            get { return GetPropertyValue<string>("LastName"); }
            set
            {
                if (UnsavedChanges.ContainsKey("LastName"))
                {
                    var cmd = (SetterCommand<string>)UnsavedChanges["LastName"];
                    cmd.Value = value;
                }
                else
                    UnsavedChanges["LastName"] = CreateSetLastNameCommand(value);

                RaisePropertyChanged("LastName");
            }
        }

        #endregion
    }
}
